在 TDD 中有個非常重要的部分就是「重構」。
測試的易讀性與易維護性,一直是一個很重要的課題。我們要能透過程式碼的結構及語意,明確傳達出測試的意圖,讓開發者清楚辨別,什麼資訊在這個測試本身是重要的,什麼是不重要的。
例如,在測試檔案 __tests__/post-editor.js:
fakePost 當中的 title 是不是 'Test Title' ,對這個測試來說並不重要,它只是代表 title ,但它具體是什麼值並不影響測試。
test('renders a form with title, content, tags, and a submit button', async () => {
...
const fakePost = {
title: 'Test Title',
content: 'Test content',
tags: ['tag1', 'tag2'],
}
...
}
我們將重構測試,改成使用工具 test-data-bot 來幫我們自動產生這些資料。
npm install --save-dev @jackfranklin/test-data-bot
或
yarn add --dev @jackfranklin/test-data-bot
引入 'test-data-bot' 中的 build、 fake 及 sequence 。
tests/post-editor.js
import {build, fake, sequence} from 'test-data-bot'
使用 test-data-bot 產生 post 及 user 的 data:
build() 建立 postBuilder ,並使用 fake() 來產生假的 title、content 跟 tagstests/post-editor.js
const postBuilder = build('Post').fields({
title: fake(f => f.lorem.words()),
content: fake(f => f.lorem.paragraphs().replace(/\r/g, '')),
tags: fake(f => [f.lorem.word(), f.lorem.word(), f.lorem.word()]),
})
因為
.paragraphs()會在段落開頭產生一行空行,所以需要加上.replace(/\r/g, '')
sequence 產生唯一的 user IDtests/post-editor.js
const userBuilder = build('User').fields({
id: sequence(s => `user-${s}`),
})
將原本的 fakeUser 改為 userBuilder() , fakePost 改為 postBuilder() :
tests/post-editor.js
test('renders a form with title, content, tags, and a submit button', async () => {
mockSavePost.mockResolvedValueOnce()
const fakeUser = userBuilder()
const {getByLabelText, getByText} = render(<Editor user={fakeUser} />)
const fakePost = postBuilder()
...
}
另外,如果有 data 對於測試本身是有意義的,也可以傳入值。
例如: postBuilder({content: 'something special'}) ,代表 content 的值 'something special' 對測試是有影響的,我們需要它。
const fakePost = postBuilder({content: 'something special'})
但在這個測試,我們不需要這麼做,所以一樣保留 postBuilder() 就好。
完成後,測試應該要亮起綠燈 ✅。
重構之後,我們可以透過測試的程式碼更清楚理解:對於這個測試,user 的值並沒有什麼特別的,post 也是,它們具體是什麼並不影響測試的結果。這可以讓我們更易於維護測試。